/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package auto;

/**
 *
 * @author Jonas
 */
public class GPSImpl implements GPS{
    private static int IDCounter=0;
    private String ID;
    private BoordComputer attachedComp;
    private boolean moving;
    private AutoMover mover;

    public GPSImpl() {
        ID = "GPS-id"+IDCounter;
        IDCounter++;
        attachedComp = null;
        moving = false;
        mover = null;
    }

    public void subscribe(BoordComputer computer) {
        attachedComp = computer;
        System.out.println("Computer "+computer+" subscribed at "+this);
    }

    public void unsubscribe() {
        if(attachedComp != null)
            System.out.println("Computer "+attachedComp+" unsubscribed");
        else
            System.out.println("No computer subscribed");
        attachedComp = null;
    }

    public void startMoving() {
        if(!moving){
            mover = new AutoMover(attachedComp);
            System.out.println("Buckle up");
            new Thread(mover).start();
        }
        moving = true;
    }

    public void stopMoving() {
        if(mover != null)
            mover.stopDriving();
        moving = false;
    }

    @Override
    public String toString() {
        return ID;
    }

    public boolean isMoving() {
        return moving;
    }
}


class AutoMover implements Runnable{
    // kruispunten die we gaan nemen
    static Location[] traject = {
        new Location(50.888,3.417),
        new Location(50.888,3.416),
        new Location(50.882,3.417),
        new Location(50.882,3.416),
        new Location(50.871,3.443),
        new Location(50.789,3.230),
        new Location(51.011,3.230),
        new Location(51.011,3.726),
        new Location(50.871,3.443),
        new Location(50.882,3.416),
        new Location(50.882,3.417),
        new Location(50.888,3.416)
    };
    // lengtes om te zorgen dat tijden een "beetje" realistisch blijven
    static int[] lengths = {1,1,0,2,10,20,20,10,2,0,1,1};
    // laatst doorgestuurde locatie
    static Location lastLocation;
    // int == index van laatst gepasseerde kruispunt
    // dus road 0 is baan tussen kruispunt0 en kruispunt1
    static int road;
    // aantal locaties verzonden OP een bepaalde weg (dus TUSSEN 2 kruispunten)
    static int distanceOnRoad;
    BoordComputer attachedComp;
    boolean driving;

    public AutoMover(BoordComputer attachedComp) {
        this.attachedComp = attachedComp;
        if(lastLocation == null){
            lastLocation = traject[0];
            distanceOnRoad = 0;
            road = 0;
        }
    }

    public void run() {
        driving = true;
        // eerste dat gestuurd wordt is de locatie waar gestart wordt (dus vanaf waar en wanneer gerekend wordt)
        attachedComp.pushData(lastLocation, System.currentTimeMillis());
        while(driving){
            try {
                // 1 ronde in 10seconden (gem 125 per stuk nodig, dus slapen tot 250)
                //Thread.sleep((int) (Math.random()*250));
                // gemiddeld 1 seconde tussen 2 GPS-pushes: random tussen 0 en 2
                Thread.sleep((int)(Math.random()*2000));
            } catch (InterruptedException ex) {}

            if(distanceOnRoad < lengths[road]){
                distanceOnRoad++;
                String prevCross = traject[road].toString();
                String nextCross = traject[(road+1)%traject.length].toString();

                double prevX = Double.parseDouble(prevCross.substring(1, prevCross.indexOf(',')));
                double nextX = Double.parseDouble(nextCross.substring(1, nextCross.indexOf(',')));
                double prevY = Double.parseDouble(prevCross.substring(prevCross.indexOf(',')+1,prevCross.indexOf(']')));
                double nextY = Double.parseDouble(nextCross.substring(nextCross.indexOf(',')+1,nextCross.indexOf(']')));

                double[] next = new double[]{
                    prevX+distanceOnRoad*(nextX-prevX)/(lengths[road]+1),
                    prevY+distanceOnRoad*(nextY-prevY)/(lengths[road]+1)
                };
                lastLocation = new Location(next[0],next[1]);
            }
            else{
                road = (road+1)%traject.length;
                lastLocation = traject[road];
                distanceOnRoad = 0;
            }
            attachedComp.pushData(lastLocation, System.currentTimeMillis());
        }
    }

    public void stopDriving() {
        this.driving = false;
    }
}